﻿////////////////////////////////////////////////////////////////////////////////////////////////////
//
//  © 2012 Stanislav S. Yarmonov.
//
//  TODO:LICENSE
//     
////////////////////////////////////////////////////////////////////////////////////////////////////
using System;
using System.Text;
using System.Collections;
using System.Collections.Generic;

namespace Pandora
{
    ////////////////////////////////////////////////////////////////////////////////////////////////
    /// <summary>
    /// Extensions for the System.Type.
    /// </summary>
    ////////////////////////////////////////////////////////////////////////////////////////////////
    public static class StringBuilderExtensions
    {
        ////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// Add string to builder.
        /// </summary>
        /// <param name="builder">
        /// Builder to add the string to.
        /// </param>
        /// <param name="value">
        /// String to be added.
        /// </param>
        /// <returns>
        /// Returns the builder for fluent-coding.
        /// </returns>
        ////////////////////////////////////////////////////////////////////////////////////////////
        public static StringBuilder Add(this StringBuilder builder, string value)
        {
            builder.Append(value);
            return builder;
        }

        ////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// Add string to builder.
        /// </summary>
        /// <param name="builder">
        /// Builder to add the string to.
        /// </param>
        /// <param name="format">
        /// Format of the string added.
        /// </param>
        /// <param name="args">
        /// String format arguments.
        /// </param>
        /// <returns>
        /// Returns the builder for fluent-coding.
        /// </returns>
        ////////////////////////////////////////////////////////////////////////////////////////////
        public static StringBuilder Add(this StringBuilder builder, string format, params object[] args)
        {
            builder.AppendFormat(format, args);
            return builder;
        }

        ////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// Add string conditionally to builder.
        /// </summary>
        /// <param name="builder">
        /// Builder to add the string to.
        /// </param>
        /// <param name="condition">
        /// Condition if string will be added.
        /// </param>
        /// <param name="value">
        /// String to be added.
        /// </param>
        /// <returns>
        /// Returns the builder for fluent-coding.
        /// </returns>
        ////////////////////////////////////////////////////////////////////////////////////////////
        public static StringBuilder Add(this StringBuilder builder, bool condition, string value)
        {
            if (condition)
            {
                builder.Append(value);
            }

            return builder;
        }

        ////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// Add string conditionally to builder.
        /// </summary>
        /// <param name="builder">
        /// Builder to add the string to.
        /// </param>
        /// <param name="condition">
        /// Condition if string will be added.
        /// </param>
        /// <param name="format">
        /// Format of the string added.
        /// </param>
        /// <param name="args">
        /// String format arguments.
        /// </param>
        /// <returns>
        /// Returns the builder for fluent-coding.
        /// </returns>
        ////////////////////////////////////////////////////////////////////////////////////////////
        public static StringBuilder Add(this StringBuilder builder, bool condition, string format, params object[] args)
        {
            if (condition)
            {
                builder.AppendFormat(format, args);
            }

            return builder;
        }

        ////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// Add string to builder with prefix and suffix.
        /// </summary>
        /// <param name="builder">
        /// Builder to add the string to.
        /// </param>
        /// <param name="value">
        /// String to be added.
        /// </param>
        /// <param name="prefix">
        /// Prefix for added item.
        /// </param>
        /// <param name="suffix">
        /// Suffix for added item.
        /// </param>
        /// <returns>
        /// Returns the builder for fluent-coding.
        /// </returns>
        ////////////////////////////////////////////////////////////////////////////////////////////
        public static StringBuilder Add(
            this StringBuilder builder,
            string value,
            string prefix,
            string suffix
        )
        {
            builder.Append(prefix);
            builder.Append(value);
            builder.Append(suffix);

            return builder;
        }

        ////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// Add items from the generic collections to the builder.
        /// </summary>
        /// <typeparam name="T">
        /// Type of the collection items.
        /// </typeparam>
        /// <param name="builder">
        /// Builder to add the items to.
        /// </param>
        /// <param name="items">
        /// Collections to get the items from.
        /// </param>
        /// <param name="extractor">
        /// Function, to get the added string value from collection item.
        /// </param>
        /// <param name="separator">
        /// Separator for the items.
        /// </param>
        /// <param name="prefix">
        /// Prefix for each added item.
        /// </param>
        /// <param name="suffix">
        /// Suffix for each added item.
        /// </param>
        /// <returns>
        /// Returns the builder for fluent-coding.
        /// </returns>
        ////////////////////////////////////////////////////////////////////////////////////////////
        public static StringBuilder Add<T>(
            this StringBuilder builder,
            IEnumerable<T> items,
            Func<T, string> extractor,
            string separator = null,
            string prefix = null,
            string suffix = null
        )
        {
            IEnumerator<T> enumerator = items.GetEnumerator();

            if (enumerator.MoveNext())
            {
                builder.Add(extractor(enumerator.Current), prefix, suffix);
            }

            while (enumerator.MoveNext())
            {
                builder
                    .Add(separator)
                    .Add(extractor(enumerator.Current), prefix, suffix)
                ;
            }

            return builder;
        }

        ////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// /// Add items from the collections to the builder.
        /// </summary>
        /// <param name="builder">
        /// Builder to add the items to.
        /// </param>
        /// <param name="items">
        /// Collections to get the items from.
        /// </param>
        /// <param name="extractor">
        /// Function, to get the added string value from collection item.
        /// </param>
        /// <param name="separator">
        /// Separator for the items.
        /// </param>
        /// <param name="prefix">
        /// Prefix for each added item.
        /// </param>
        /// <param name="suffix">
        /// Suffix for each added item.
        /// </param>
        /// <returns>
        /// Returns the builder for fluent-coding.
        /// </returns>
        ////////////////////////////////////////////////////////////////////////////////////////////
        public static StringBuilder Add(
            this StringBuilder builder,
            IEnumerable items,
            Func<object, string> extractor,
            string separator,
            string prefix = null,
            string suffix = null
        )
        {
            IEnumerator enumerator = items.GetEnumerator();

            if (enumerator.MoveNext())
            {
                builder.Add(extractor(enumerator.Current), prefix, suffix);
            }

            while (enumerator.MoveNext())
            {
                builder
                    .Add(separator)
                    .Add(extractor(enumerator.Current), prefix, suffix)
                ;
            }

            return builder;
        }
    }
}
